package com.hzsoft.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.SqlSessionFactory;
import org.dom4j.Element;

/**
 * java bean 反射的方法
 * @author Michael
 */
public class BeanRefUtil {

	/**
	 * 取Bean的属性和值对应关系的MAP
	 * @param bean
	 * @return Map
	 */
	public static Map<String, String> getFieldValueMap(Object bean) {
		Class<?> cls = bean.getClass();
		Class<?> cls1 = bean.getClass().getSuperclass();
		Map<String, String> valueMap = new HashMap<String, String>();
		// 取出bean里的所有方法
		Method[] methods1 = cls1.getDeclaredMethods();
		Field[] fields1 = cls1.getDeclaredFields();
		Method[] methods2 = cls.getDeclaredMethods();
		Field[] fields2 = cls.getDeclaredFields();

		List<Field> flist = new ArrayList<Field>();
		for (Field field : fields1) {
			flist.add(field);
		}
		for (Field field : fields2) {
			flist.add(field);
		}
		List<Method> mlist = new ArrayList<Method>();
		for (Method method : methods1) {
			mlist.add(method);
		}
		for (Method method : methods2) {
			mlist.add(method);
		}
		Field[] fields = new Field[flist.size()];
		for (int i=0;i<flist.size();i++) {
			fields[i]=flist.get(i);
		}
		
		Method[] methods = new Method[mlist.size()];
		for (int i=0;i<mlist.size();i++) {
			methods[i]=mlist.get(i);
		}
		for(Field field : fields) {
			try {
				String fieldType = field.getType().getSimpleName();
				String fieldGetName = parGetName(field.getName());
				if (!checkGetMet(methods, fieldGetName)) {
					continue;
				}
				Method fieldGetMet = cls
						.getMethod(fieldGetName, new Class[] {});
				Object fieldVal = fieldGetMet.invoke(bean, new Object[] {});
				String result = null;
				if ("Date".equals(fieldType)) {
					result = fmtDate((Date) fieldVal);
				} else {
					if (null != fieldVal) {
						result = String.valueOf(fieldVal);
					}
				}
				//加入类型判断
				if("String".equals(fieldType)
						|| "Short".equals(fieldType)
						|| "BigDecimal".equals(fieldType)
						|| "Boolean".equals(fieldType)
						|| "Double".equals(fieldType)
						|| "Long".equals(fieldType)
						|| "Integer".equals(fieldType)
						|| "int".equals(fieldType)
						|| "long".equals(fieldType)
						|| "short".equals(fieldType)
						|| "Date".equals(fieldType)
						|| "float".equals(fieldType)){
					valueMap.put(field.getName(), result);
				}
			} catch (Exception e) {
				continue;
			}
		}
		return valueMap;
	}

	/**
	 * set属性的值到Bean
	 * @param bean
	 * @param valMap
	 */
	public static void setFieldValue(Object bean, Map<String, String> valMap) {
		if(bean == null) return ;
		Class<?> cls = bean.getClass();
		Class<?> cls1 = bean.getClass().getSuperclass();
		// 取出bean里的所有方法
		Method[] methods1 = cls1.getDeclaredMethods();
		Field[] fields1 = cls1.getDeclaredFields();
		Method[] methods2 = cls.getDeclaredMethods();
		Field[] fields2 = cls.getDeclaredFields();

		List<Field> flist = new ArrayList<Field>();
		for (Field field : fields1) {
			flist.add(field);
		}
		for (Field field : fields2) {
			flist.add(field);
		}
		List<Method> mlist = new ArrayList<Method>();
		for (Method method : methods1) {
			mlist.add(method);
		}
		for (Method method : methods2) {
			mlist.add(method);
		}
		Field[] fields = new Field[flist.size()];
		for (int i=0;i<flist.size();i++) {
			fields[i]=flist.get(i);
		}
		
		Method[] methods = new Method[mlist.size()];
		for (int i=0;i<mlist.size();i++) {
			methods[i]=mlist.get(i);
		}

		for (Field field : fields) {
			try {
				String fieldSetName = parSetName(field.getName());
				if (!checkSetMet(methods, fieldSetName)) {
					continue;
				}
				Method fieldSetMet = cls.getMethod(fieldSetName,
						field.getType());
				String value = valMap.get(field.getName());
				if (null != value && !"".equals(value) && !"null".equalsIgnoreCase(value)) {
					String fieldType = field.getType().getSimpleName();
					if ("String".equals(fieldType)) {
						fieldSetMet.invoke(bean, value);
						
					} else if ("Date".equals(fieldType)) {
						Date temp = parseDate(value);
						fieldSetMet.invoke(bean, temp);
					} else if ("Integer".equals(fieldType)
							|| "int".equals(fieldType)) {
						Integer intval = Integer.parseInt(value);
						fieldSetMet.invoke(bean, intval);
					} else if ("Long".equalsIgnoreCase(fieldType)) {
						Long temp = Long.parseLong(value);
						fieldSetMet.invoke(bean, temp);
					} else if ("Double".equalsIgnoreCase(fieldType)) {
						Double temp = Double.parseDouble(value);
						fieldSetMet.invoke(bean, temp);
					} else if ("Boolean".equalsIgnoreCase(fieldType)) {
						Boolean temp = Boolean.parseBoolean(value);
						fieldSetMet.invoke(bean, temp);
					} else if ("BigDecimal".equalsIgnoreCase(fieldType)) {
						BigDecimal temp = new BigDecimal(value);
						fieldSetMet.invoke(bean, temp);
					} else if ("Short".equalsIgnoreCase(fieldType)) {
						Short temp = Short.parseShort(value);
						fieldSetMet.invoke(bean, temp);
					} else {
						System.out.println("not supper type" + fieldType);
					}
				}
			} catch (Exception e) {
				continue;
			}
		}
	}
	
	@SuppressWarnings("all")
	public static Object elementToObj(Element element,SqlSessionFactory sf,String resultmapName,Class cc){
		ResultMap rm = sf.getConfiguration().getResultMap(resultmapName);
		
		Map<String,String> map = new HashMap<String,String>();
		List<ResultMapping> list = rm.getResultMappings();
		for(int i=0;i<list.size();i++){
			ResultMapping r = (ResultMapping)list.get(i);
			if(null==r.getNestedQueryId()){
				map.put( r.getColumn(),r.getProperty());
			}
		}
		Map<String,String> m=new HashMap<String,String>();
		
		List<Element> es=element.elements("field");
		for(Element e:es){
			String key = map.get(e.attributeValue("name"));
			if(!"".equals(key)){
				m.put(key, e.getTextTrim());
			}
		}
		
		Object obj=null;
		try {
			obj = cc.newInstance();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		}
		setFieldValue(obj,m);
		return obj;
	}

	/**
	 * 格式化string为Date
	 * 
	 * @param datestr
	 * @return date
	 */
	public static Date parseDate(String datestr) {
		if (null == datestr || "".equals(datestr)) {
			return null;
		}
		try {
			String fmtstr = null;
			if (datestr.indexOf(':') > 0) {
				fmtstr = "yyyy-MM-dd HH:mm:ss";
			} else {

				fmtstr = "yyyy-MM-dd";
			}
			//SimpleDateFormat sdf = new SimpleDateFormat(fmtstr, Locale.UK);
			SimpleDateFormat sdf = new SimpleDateFormat(fmtstr);
			return sdf.parse(datestr);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 日期转化为String
	 * 
	 * @param date
	 * @return date string
	 */
	public static String fmtDate(Date date) {
		if (null == date) {
			return null;
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
					Locale.US);
			return sdf.format(date);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 判断是否存在某属性的 set方法
	 * 
	 * @param methods
	 * @param fieldSetMet
	 * @return boolean
	 */
	public static boolean checkSetMet(Method[] methods, String fieldSetMet) {
		for (Method met : methods) {
			if (fieldSetMet.equals(met.getName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断是否存在某属性的 get方法
	 * 
	 * @param methods
	 * @param fieldGetMet
	 * @return boolean
	 */
	public static boolean checkGetMet(Method[] methods, String fieldGetMet) {
		for (Method met : methods) {
			if (fieldGetMet.equals(met.getName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 拼接某属性的 get方法
	 * 
	 * @param fieldName
	 * @return String
	 */
	public static String parGetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		return "get" + decapitalize(fieldName);
	}

	/**
	 * 拼接在某属性的 set方法
	 * 
	 * @param fieldName
	 * @return String
	 */
	public static String parSetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		return "set" + decapitalize(fieldName);
	}

	/**
	 * 属性的get、set方法名称取得
	 * 
	 * @param s
	 * @return
	 */
	public static String decapitalize(String s) {
		if (s == null || s.length() == 0)
			// 空处理
			return s;

		if (s.length() > 1 && Character.isUpperCase(s.charAt(1))
				&& Character.isUpperCase(s.charAt(0))) {
			// 长度大于1，并且前两个字符大写时，返回原字符串
			return s;
		} else if (s.length() > 1 && Character.isUpperCase(s.charAt(1))) {
			// 长度大于1，并且前两个字符大写时，返回原字符串
			return s;
		} else {
			// 其他情况下，把原字符串的首个字符小写处理后返回
			char ac[] = s.toCharArray();
			// ac[0] = Character.toLowerCase(ac[0]);
			ac[0] = Character.toUpperCase(ac[0]);
			return new String(ac);
		}
	}

}